原本以為已經差不多有 Shell 的樣子了,結果剛剛試了一下竟然不能 cd,這 Shell 真是爛得徹底,竟然連 cd 都不行,這樣也能叫做 Shell 嗎???

各位客倌先別激動,且聽筆者我來娓娓道來
之前在 Day2 跟 Day5 有說過,Shell 收到指令之後會到系統的 PATH 裡面尋找執行檔,接著再啟動一個 Process 來執行它,如下圖

也可以用 which 來看到某個指令的執行檔放在哪裡,像 ls、ps 跟 mv 都是放在 /bin 裡面

但神奇的事情發生了,用 which cd 去看 cd 執行檔時卻顯示 shell built-in command,也就是所謂的 Shell 內建指令,意思是他不是一個執行檔,而是 Shell 要自己實作的指令

cd ?cd 指令的目的是要改變目前 Shell 的 Working Directory,但因為 每一個 Process 有自己的 Working Directory(包括 Shell),所以 Shell 沒辦法另外開一個 Process 來幫他自身進行 cd ,而是 Shell 本身收到 cd 指令後要變更自己的資料夾
總而言之,Shell 的 cd 指令沒辦法讓其他 Process 幫忙做,一定得自己做才行

懂了這個觀念之後就來看看怎麼做吧
os.Chdir(dir string)Chdir 也是一個 System Call,他可以切換目前 Process 的 Working Directory,所以要用它來實作 cd
executeInputfunc executeInput(input string) error {
args := strings.Split(input, " ")
if args[0] == "cd" {
// 如果指令是 cd dirname
// 就跑 os.Chdir(dirname)
err := os.Chdir(args[1])
// 並回傳發生的錯誤(例如資料夾不存在)
return err
}
cmd := exec.Command(args[0], args[1:]...)
// ...
}
如果使用者輸入的指令是 cd dirname,那就使用 os.Chdir 來切換 Working Directory,而不是另外開一個 Process 來跑 cd,因為 cd 一定要是自己跑
總算是可以正常 cd 囉,ls 的結果也確實是那個資料夾的

其實像 cd 這樣的內建指令還有很多,像是 exit 跟 alias,只要是改變 Shell 內部狀態的功能都必須是內建指令,因為另外啟動 Process 並不能改變目前 Shell 的狀態

今天的 commit 放在這裡,有什麼問題歡迎在下方提問,沒問題的話就明天見囉~